﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ReferenceSwap.Utility
{
    public partial class Form1 : Form
    {
        ProjectData project;
        SolutionData solution;
        string assemblyDirectory;
        string buildConfig;
        string workerError;
        bool copyFiles;


        public Form1()
        {
            InitializeComponent();
        }

        private void btnRun_Click(object sender, EventArgs e)
        {
            // todo: gross - use validators
            if (project == null)
            {
                MessageBox.Show("Select a valid project.");
                return;
            }

            assemblyDirectory = txtAssemblyDirectory.Text;

            if (string.IsNullOrEmpty(assemblyDirectory))
            {
                MessageBox.Show("Select a valid target directory");
                return;
            }

            buildConfig = comboBuildConfig.SelectedItem.ToString();

            if (string.IsNullOrEmpty(buildConfig))
            {
                MessageBox.Show("Enter a valid build configuration");
                return;
            }

            copyFiles = chkCopyFiles.Checked;

            workerError = "";

            lblInfo.Text = "Running...";

            btnRun.Enabled = false;

            List<ProjectReference> selectedRefs = FindSelectedReferences();

            progressBar1.Style = ProgressBarStyle.Marquee;
            progressBar1.MarqueeAnimationSpeed = 20;

            backgroundWorker1.RunWorkerAsync(selectedRefs);
        }



        private void btnAssemblyDirectory_Click(object sender, EventArgs e)
        {
            try
            {
                DialogResult res = folderBrowserDialog1.ShowDialog();

                if (res == System.Windows.Forms.DialogResult.OK)
                {
                    txtAssemblyDirectory.Text = folderBrowserDialog1.SelectedPath;
                }
            }
            catch (Exception ex)
            {
                ShowError(ex);
            }
        }

        private void btnSolutionBrowse_Click(object sender, EventArgs e)
        {
            try
            {
                diagOpenProject.Filter = "Solution Files|*.sln";
                DialogResult res = diagOpenProject.ShowDialog();

                if (res == System.Windows.Forms.DialogResult.OK)
                {
                    txtSolutionFile.Text = diagOpenProject.FileName;
                }
            }
            catch (Exception ex)
            {
                ShowError(ex);
            }
        }

        private void btnProjectBrowse_Click(object sender, EventArgs e)
        {
            try
            {
                diagOpenProject.Filter = "C# Project Files|*.csproj";
                DialogResult res = diagOpenProject.ShowDialog();

                if (res == System.Windows.Forms.DialogResult.OK)
                {
                    txtProjectFile.Text = diagOpenProject.FileName;
                }
            }
            catch (Exception ex)
            {
                ShowError(ex);
            }
        }

        private void txtProjectFile_TextChanged(object sender, EventArgs e)
        {
            try
            {
                project = new ProjectData(txtProjectFile.Text);
                LoadReferences(project.ProjectReferences);
            }
            catch (Exception ex)
            {
                ShowError(ex);
            }

            if (project != null)
            {
                try
                {
                    solution = project.FindSolution();
                    // remove the event just for a moment while we update the data
                    txtSolutionFile.TextChanged -= txtSolutionFile_TextChanged;
                    txtSolutionFile.Text = solution.SolutionFile.FullName;
                    txtSolutionFile.TextChanged += txtSolutionFile_TextChanged;
                }
                catch (Exception ex)
                {
                    // hack: ignore the auto-locate error
                    if (ex.Message != "Unable to auto-locate solution file")
                        ShowError(ex);
                }
            }
        }

        private void txtSolutionFile_TextChanged(object sender, EventArgs e)
        {
            try
            {
                solution = new SolutionData(txtSolutionFile.Text);
            }
            catch (Exception ex)
            {
                ShowError(ex);
            }
        }

        private void LoadReferences(List<ProjectReference> refs)
        {
            pnlReferences.Controls.Clear();

            if (project == null) return;

            foreach (ProjectReference reference in refs)
            {
                pnlReferences.Controls.Add(new ProjectReferenceControl(reference));
            }
        }

        private List<ProjectReference> FindSelectedReferences()
        {
            List<ProjectReference> refs = new List<ProjectReference>();

            foreach (Control ctrl in pnlReferences.Controls)
            {
                ProjectReferenceControl c = ctrl as ProjectReferenceControl;

                if (c != null && c.Swap)
                {
                    refs.Add(c.Reference);
                }
            }

            return refs;
        }

        private void ShowError(Exception ex)
        {
            MessageBox.Show(string.Format("Error: {0}{1}{2}", ex.GetType().ToString(), Environment.NewLine, ex.Message));
        }

        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            ReferenceManager mgr = new ReferenceManager();
            List<ProjectReference> selectedRefs = (List<ProjectReference>)e.Argument;
            try
            {
                mgr.SwapToAssemblyReference(project, selectedRefs, assemblyDirectory, buildConfig, copyFiles);

                if (solution != null)
                    mgr.RemoveReferencesFromSolution(solution, selectedRefs);

            }
            catch (Exception ex)
            {
                workerError = ex.Message;
            }
        }

        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            btnRun.Enabled = true;

            progressBar1.MarqueeAnimationSpeed = 0;
            progressBar1.Style = ProgressBarStyle.Blocks;
            progressBar1.Value = 100;

            lblInfo.Text = string.IsNullOrEmpty(workerError) ? "Successfully completed." : workerError;
        }

        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {

        }

        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            foreach (Control ctrl in pnlReferences.Controls)
            {
                ProjectReferenceControl c = ctrl as ProjectReferenceControl;

                if (c != null)
                    c.Swap = checkBox1.Checked;
            }
        }
    }
}
